/*
 * 描述： 金額分配
 * 修改人： Weng.weng
 * 修改时间： 2021年8月23日
 * 项目： amount-allocation-demo
 */
package com.tuozixuan.allocation;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import com.tuozixuan.allocation.amount.Amount;
import com.tuozixuan.allocation.constant.AmountType;

/**
 * 金額分配<br>
 * 
 * @author Weng.weng
 * @version [版本号, 2021年8月23日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class AllocationService {
	
	/**
	 * 
	 * 金額分配<br>
	 *
	 * @param amountList 按照還款優先級排列的金額信息列表
	 * @param amount 還款金額
	 * @param exemptAmountMap 豁免金額信息
	 * @return BigDecimal 剩餘金額
	 * @version [版本号, 2021年8月23日]
	 * @author Weng.weng
	 */
	public TxAmount assignAmount(List<AmountType> priorityList, BigDecimal amount, Map<AmountType, Amount> amountMap, 
			Map<AmountType, BigDecimal> exemptAmountMap) {
		
		BigDecimal remainAmount = amount;
		for (AmountType amountType : priorityList) {
			
			Amount amountItem = amountMap.get(amountType);
			
			// 扣減豁免金額
			BigDecimal localTotal = this.deductExemptAmount(amountItem, exemptAmountMap);
			
			// 分配金額
			remainAmount = this.assignItem(amountItem, localTotal, remainAmount);
//			if (remainAmount.compareTo(BigDecimal.ZERO) <= 0) {
//				break;
//			}
		}
		return new TxAmount(amountMap, remainAmount, exemptAmountMap);
	}
	
	private BigDecimal deductExemptAmount(Amount amountItem, Map<AmountType, BigDecimal> exemptAmountMap) {
		BigDecimal exemptAmount = exemptAmountMap.getOrDefault(amountItem.getType(), BigDecimal.ZERO);
		// 實際應還金額 = 應還金額 + 豁免金額
		BigDecimal localTotal = amountItem.getTotal().add(exemptAmount);
		if (localTotal.compareTo(BigDecimal.ZERO) < 0) {
			localTotal = BigDecimal.ZERO;
			//exemptAmountMap.put(amountItem.getType(), amountItem.getTotal().negate());
			amountItem.setExempt(amountItem.getTotal().negate());
		} else {
			amountItem.setExempt(exemptAmount);
		}
		return localTotal;
	}
	
	private BigDecimal assignItem(Amount amountItem, BigDecimal total, BigDecimal remainAmount) {
		if (remainAmount.compareTo(total) > 0) {
			// 如果可分配的金額大於應還金額，則實還金額=應還金額，剩餘可分配金額減去應還金額
			amountItem.setActual(total);
			amountItem.setRemain(BigDecimal.ZERO);
			remainAmount = remainAmount.subtract(total);
		} else {
			// 如果可分配金額小於等於應還金額，則實還金額=可分配金額，剩餘可分配金額等於0
			amountItem.setActual(remainAmount);
			amountItem.setRemain(total.subtract(remainAmount));
			remainAmount = BigDecimal.ZERO;
		}
		return remainAmount;
	}
}
